#include <gtest/gtest.h>
#include "viml/builtin_path.h"
#include "viml/value.h"
#include <filesystem>

namespace fs = std::filesystem;

namespace viml {

class BuiltinPathTest : public ::testing::Test {
protected:
    // 测试辅助函数
    static std::string normalize_separators(const std::string& path) {
        std::string result = path;
        std::replace(result.begin(), result.end(), '\\', '/');
        return result;
    }
};

// ========================================
// 路径拼接测试
// ========================================

TEST_F(BuiltinPathTest, PathJoinTwo) {
    auto result = path_join_builtin({Value::string("home"), Value::string("user")});
    EXPECT_TRUE(result.is_string());
    
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "home/user");
}

TEST_F(BuiltinPathTest, PathJoinMultiple) {
    auto result = path_join_builtin({
        Value::string("home"),
        Value::string("user"),
        Value::string("documents"),
        Value::string("file.txt")
    });
    
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "home/user/documents/file.txt");
}

TEST_F(BuiltinPathTest, PathJoinSingle) {
    auto result = path_join_builtin({Value::string("test")});
    EXPECT_EQ(result.as_string(), "test");
}

TEST_F(BuiltinPathTest, PathJoinEmpty) {
    EXPECT_THROW(path_join_builtin({}), std::runtime_error);
}

TEST_F(BuiltinPathTest, PathJoinInvalidType) {
    EXPECT_THROW(
        path_join_builtin({Value::string("test"), Value::make_number(123)}),
        std::runtime_error
    );
}

// ========================================
// 路径规范化测试
// ========================================

TEST_F(BuiltinPathTest, PathNormalize) {
    auto result = path_normalize_builtin({Value::string("a//b/./c/../d")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "a/b/d");
}

TEST_F(BuiltinPathTest, PathNormalizeDoubleDots) {
    auto result = path_normalize_builtin({Value::string("a/b/../c")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "a/c");
}

TEST_F(BuiltinPathTest, PathNormalizeDot) {
    auto result = path_normalize_builtin({Value::string("./a/./b/.")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "a/b");
}

TEST_F(BuiltinPathTest, PathNormalizeInvalidArgs) {
    EXPECT_THROW(path_normalize_builtin({}), std::runtime_error);
    EXPECT_THROW(path_normalize_builtin({Value::make_number(123)}), std::runtime_error);
}

// ========================================
// 绝对路径测试
// ========================================

TEST_F(BuiltinPathTest, PathAbsolute) {
    auto result = path_absolute_builtin({Value::string("test")});
    EXPECT_TRUE(result.is_string());
    
    std::string path = result.as_string();
    // 绝对路径应该包含当前工作目录
    EXPECT_FALSE(path.empty());
    
#ifdef _WIN32
    // Windows路径应该包含驱动器号
    EXPECT_TRUE(path.length() >= 3 && path[1] == ':');
#else
    // Unix路径应该以/开头
    EXPECT_EQ(path[0], '/');
#endif
}

TEST_F(BuiltinPathTest, PathAbsoluteInvalidArgs) {
    EXPECT_THROW(path_absolute_builtin({}), std::runtime_error);
    EXPECT_THROW(path_absolute_builtin({Value::make_number(123)}), std::runtime_error);
}

// ========================================
// 路径解析测试
// ========================================

TEST_F(BuiltinPathTest, PathDirname) {
    auto result = path_dirname_builtin({Value::string("/home/user/file.txt")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "/home/user");
}

TEST_F(BuiltinPathTest, PathDirnameNoDir) {
    auto result = path_dirname_builtin({Value::string("file.txt")});
    EXPECT_EQ(result.as_string(), "");
}

TEST_F(BuiltinPathTest, PathDirnameRoot) {
    auto result = path_dirname_builtin({Value::string("/file.txt")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "/");
}

TEST_F(BuiltinPathTest, PathBasename) {
    auto result = path_basename_builtin({Value::string("/home/user/file.txt")});
    EXPECT_EQ(result.as_string(), "file.txt");
}

TEST_F(BuiltinPathTest, PathBasenameNoDir) {
    auto result = path_basename_builtin({Value::string("file.txt")});
    EXPECT_EQ(result.as_string(), "file.txt");
}

TEST_F(BuiltinPathTest, PathBasenameTrailingSlash) {
    auto result = path_basename_builtin({Value::string("/home/user/")});
    EXPECT_EQ(result.as_string(), "user");
}

TEST_F(BuiltinPathTest, PathExtension) {
    auto result = path_extension_builtin({Value::string("file.txt")});
    EXPECT_EQ(result.as_string(), ".txt");
}

TEST_F(BuiltinPathTest, PathExtensionMultipleDots) {
    auto result = path_extension_builtin({Value::string("archive.tar.gz")});
    EXPECT_EQ(result.as_string(), ".gz");
}

TEST_F(BuiltinPathTest, PathExtensionNone) {
    auto result = path_extension_builtin({Value::string("file")});
    EXPECT_EQ(result.as_string(), "");
}

TEST_F(BuiltinPathTest, PathExtensionHiddenFile) {
    auto result = path_extension_builtin({Value::string(".gitignore")});
    EXPECT_EQ(result.as_string(), "");
}

// ========================================
// 路径分隔符测试
// ========================================

TEST_F(BuiltinPathTest, PathSeparator) {
    auto result = path_separator_builtin({});
    EXPECT_TRUE(result.is_string());
    
    std::string sep = result.as_string();
    EXPECT_EQ(sep.length(), 1);
    
#ifdef _WIN32
    EXPECT_EQ(sep, "\\");
#else
    EXPECT_EQ(sep, "/");
#endif
}

// ========================================
// 综合测试
// ========================================

TEST_F(BuiltinPathTest, ComplexPathOperations) {
    // 拼接路径
    auto joined = path_join_builtin({
        Value::string("home"),
        Value::string("user"),
        Value::string("documents")
    });
    
    // 规范化
    auto normalized = path_normalize_builtin({joined});
    
    // 获取目录名
    auto dirname = path_dirname_builtin({normalized});
    std::string dir_str = normalize_separators(dirname.as_string());
    EXPECT_EQ(dir_str, "home/user");
    
    // 获取基本名
    auto basename = path_basename_builtin({normalized});
    EXPECT_EQ(basename.as_string(), "documents");
}

TEST_F(BuiltinPathTest, PathWithExtensions) {
    std::string filename = "document.backup.txt";
    
    auto ext = path_extension_builtin({Value::string(filename)});
    EXPECT_EQ(ext.as_string(), ".txt");
    
    auto base = path_basename_builtin({Value::string(filename)});
    EXPECT_EQ(base.as_string(), filename);
}

// ========================================
// 边界情况测试
// ========================================

TEST_F(BuiltinPathTest, EmptyPath) {
    auto result = path_normalize_builtin({Value::string("")});
    EXPECT_EQ(result.as_string(), ".");
}

TEST_F(BuiltinPathTest, RootPath) {
    auto result = path_normalize_builtin({Value::string("/")});
    std::string path = normalize_separators(result.as_string());
    EXPECT_EQ(path, "/");
}

TEST_F(BuiltinPathTest, CurrentDirectory) {
    auto result = path_normalize_builtin({Value::string(".")});
    EXPECT_EQ(result.as_string(), ".");
}

TEST_F(BuiltinPathTest, ParentDirectory) {
    auto result = path_normalize_builtin({Value::string("..")});
    EXPECT_EQ(result.as_string(), "..");
}

} // namespace viml
